#include "league.h"
#include <iostream>
#define ROUND 100

extern int** Payoff;
extern int MATRIXWIDTH;
extern int bestchoice;

int League::turn = 0;
int League::p1act = 0;
int League::p2act = 0;
int League::p1score = 0;
int League::p2score = 0;
int League::p1prevact[5];  // before n turn ( 0 = this turn)
int League::p2prevact[5];
int League::p1prevscore[5];
int League::p2prevscore[5];	
float League::p1avscore;
float League::p2avscore;
int League::error1;
int League::error2;



using namespace std;


League::League(Population &pro, Population &anti)
{

	/*run versus for each of the participants*/
	int proSize = pro.size();
	int antiSize = anti.size();
	numberofplayers = proSize + antiSize;

	int a=0;
	int b=0;
	
	turn  = 0;
	p1act = 0;
	p2act = 0;
	p1score = 0;
	p2score = 0;
	p1avscore = 0.0;
	p2avscore = 0.0;
	error1 = 0;
	error2 = 0;
	
	/** initialize scores **/
	for(int i=0; i<pro.size(); i++)
	{
		pro.raw[i]->score = 0;
		pro.raw[i]->age ++;
	}

	for(int i=0; i<anti.size(); i++)
	{
		anti.raw[i]->score = 0;
		anti.raw[i]->age ++;
	}



	for (a=0; a<numberofplayers; a++)
	{
		/** init player 1**/
		Genome& player1 = a < pro.size() ? *pro.raw[a] : *anti.raw[a-pro.size()];
		list<Decision> &arules = player1.rules;

//		for(list<Decision>::iterator i = arules.begin(); i!=arules.end(); i++)
//			printf("%d ", i->raw[30]);


		for (b=a+1; b<numberofplayers; b++)
		{
			/** init player 2**/
			Genome& player2 = b < pro.size() ? *pro.raw[b] : *anti.raw[b-pro.size()];
			list<Decision> &brules = player2.rules;
			
			/** init round **/
			turn=1;
			for (int c=0; c<5; c++)
			{
				p1prevact[c]=-1;
				p1prevscore[c]=-1;
				p2prevact[c]=-1;
				p2prevscore[c]=-1;
			}
			p1score=0;
			p2score=0;
			p1avscore=-1.0;
			p2avscore=-1.0;

			/** run versus! **/
			versus(arules,brules);
			
			if(a < pro.size()) 
				player1.score += (p1score + (p1score > p2score ? 0.05 : 0));
			else
				player1.score += p1score*2 - p2score;

			if(b < pro.size())
				player2.score += (p2score + (p2score > p1score ? 0.05 : 0));
			else
				player2.score += p2score*2 - p1score;

			player1.totalScore += player1.score;
			player2.totalScore += player2.score;

		}

	}

	
}

void League::versus(list<Decision> &arules, list<Decision>&brules)
{
	int c = 0;
	//round start
	for(turn=1; turn<=ROUND; turn++)
	{
		error1=0;
		error2=0;

		p1act=getaction(arules,turn,p1prevact,p2prevact,p1prevscore,p2prevscore,p1avscore,p2avscore);
		p2act=getaction(brules,turn,p2prevact,p1prevact,p2prevscore,p1prevscore,p2avscore,p1avscore);

		if(p1act > MATRIXWIDTH || p1act <= 0)
		{
			error1=20;
			printf("%d,%d\n",p1act, MATRIXWIDTH);
			p1act=1;		
		}
		if(p2act > MATRIXWIDTH || p2act <= 0)
		{
			error2=20;
			p2act=1;
		}

		p1score=p1score+Payoff[p1act-1][p2act-1]-error1;
		p2score=p2score+Payoff[p2act-1][p1act-1]-error2;

		p1prevact[0]=p1act;
		p2prevact[0]=p2act;
		p1prevscore[0]=Payoff[p1act-1][p2act-1];
		p2prevscore[0]=Payoff[p2act-1][p1act-1];
		for (c=4; c>0; c--)	
		{
			p1prevact[c]=p1prevact[c-1];
			p2prevact[c]=p2prevact[c-1];
			p1prevscore[c]=p1prevscore[c-1];
			p2prevscore[c]=p2prevscore[c-1];
		}

		p1avscore=(float) p1score / (float) turn;
		p2avscore=(float) p2score / (float) turn;
	}
}



int League::getaction(list<Decision> &rules,int turn,int* myactprev,int* youractprev,int* myscoreprev,int* yourscoreprev,
		float myavscore,float youravscore)
{
	int a=0;
	int b=0;
	int sw=0;

	for (list<Decision>::iterator iter = rules.begin(); iter != rules.end(); iter ++ )
	{
		sw=0;
		if((iter->raw[0]<=turn && iter->raw[1]>=turn) || (iter->raw[0]==-1 && iter->raw[1]==-1))
		{
			for (b=1; b<5; b++)
			{
				if (iter->raw[b*6-4]!=myactprev[b] && iter->raw[b*6-4]!=-1)
				{
					sw=1;
					break;
				}
				if (iter->raw[b*6-3]!=youractprev[b] && iter->raw[b*6-3]!=-1)
				{
					sw=1;
					break;
				}
				if (
				    (iter->raw[b*6-2] > myscoreprev[b] || iter->raw[b*6-1] < myscoreprev[b])
				   && (iter->raw[b*6-2] != -1 && iter->raw[b*6-1] != -1)
				   )
				{
					sw=1;
					break;
				}
				if (
				    (iter->raw[b*6] > yourscoreprev[b] || iter->raw[b*6+1] < yourscoreprev[b])
				   && (iter->raw[b*6] != -1 && iter->raw[b*6+1] != -1)
				   )
				{
					sw=1;
					break;
				}

			}
			if (sw==0)
			{
				if((iter->raw[26]<=(int) myavscore && iter->raw[27]>=(int) myavscore) 
						|| (iter->raw[26]==-1 && iter->raw[27]==-1))
				{
					if((iter->raw[28]<=(int) youravscore && iter->raw[29]>=(int) youravscore) 
						|| (iter->raw[28]==-1 && iter->raw[29]==-1))
					{
						return iter->raw[30];
					}
				}
			}
		}
	}
	return bestchoice;
}


